package hos.permission;

import android.Manifest;
import android.content.Intent;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;

import androidx.activity.ComponentActivity;
import androidx.activity.result.ActivityResult;
import androidx.activity.result.ActivityResultCallback;
import androidx.activity.result.ActivityResultCaller;
import androidx.activity.result.ActivityResultLauncher;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentManager;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleEventObserver;
import androidx.lifecycle.LifecycleOwner;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import hos.permission.dialog.DefaultDialog;
import hos.permission.dialog.RationaleDialog;
import hos.permission.dialog.RationaleDialogFragment;

/**
 * <p>Title: PermissionRequest </p>
 * <p>Description:  </p>
 * <p>Company: www.mapuni.com </p>
 *
 * @author : 蔡俊峰
 * @version : 1.0
 * @date : 2024-01-10 22:33
 */
public class PermissionDelegate implements PermissionRequest {
    @Nullable
    private LifecycleOwner lifecycleOwner;
    @NonNull
    private final List<String> permissions = new ArrayList<>();
    @NonNull
    private final List<String> normalPermissions = new ArrayList<>();
    @NonNull
    private final List<String> specialPermissions = new ArrayList<String>();

    @Nullable
    private OnPermissionResultListener.onRefusedListener refusedListener;
    @Nullable
    private OnPermissionResultListener.onSuccessListener successListener;
    @Nullable
    private OnPermissionResultListener.onSuccessFulListener successFulListener;
    @Nullable
    private OnPermissionResultListener.onRefusedDialogListener refusedDialogListener;
    @Nullable
    private OnPermissionResultListener.onRequestDialogListener requestDialogListener;
    @Nullable
    private OnPermissionResultListener.onCancelListener cancelListener;

    private boolean isSuccess;

    @NonNull
    public static PermissionRequest create(ComponentActivity activity) {
        return new PermissionDelegate(activity);
    }

    @NonNull
    public static PermissionRequest create(Fragment fragment) {
        return new PermissionDelegate(fragment);
    }

    private PermissionDelegate(@NonNull LifecycleOwner lifecycleOwner) {
        this.lifecycleOwner = lifecycleOwner;
        lifecycleOwner.getLifecycle().addObserver(new LifecycleEventObserver() {
            @Override
            public void onStateChanged(@NonNull LifecycleOwner lifecycleOwner, @NonNull Lifecycle.Event event) {
                switch (event) {
                    case ON_CREATE:
                        // 初始化
                        getRequestNormalPermissionLauncher();
                        getRequestInstallPackagesLauncher();
                        getRequestBackgroundLocationFrontLauncher();
                        getRequestBackgroundLocationLauncher();
                        getForwardToSettingsLauncher();
                        getRequestBodySensorsBackgroundLauncher();
                        getRequestSystemAlertWindowLauncher();
                        getRequestNotificationLauncher();
                        getRequestWriteSettingsLauncher();
                        getRequestManageExternalStoragePermissionLauncher();
                        getRequestManageExternalStorageLauncher();
                        break;
                    case ON_START:
                        Log.d("TestPresenter", "onStart");
                        break;
                    case ON_RESUME:
                        Log.d("TestPresenter", "onResume");
                        break;
                    case ON_PAUSE:
                        Log.d("TestPresenter", "onPause");
                        break;
                    case ON_STOP:
                        Log.d("TestPresenter", "onStop");
                        break;
                    case ON_DESTROY:
                        dispose();
                        lifecycleOwner.getLifecycle().removeObserver(this);
                        break;
                    case ON_ANY:
                        Log.d("TestPresenter", "onAny");
                        break;
                }
            }
        });
    }

    @NonNull
    private ComponentActivity requireActivity() {
        if (lifecycleOwner instanceof ComponentActivity) {
            return (ComponentActivity) lifecycleOwner;
        }
        if (lifecycleOwner instanceof Fragment) {
            return ((Fragment) lifecycleOwner).requireActivity();
        }
        throw new IllegalStateException("PermissionDelegate " + this + " null an activity.");
    }

    @NonNull
    private ActivityResultCaller requireActivityResultCaller() {
        if (lifecycleOwner instanceof ActivityResultCaller) {
            return (ActivityResultCaller) lifecycleOwner;
        }
        throw new IllegalStateException("PermissionDelegate " + this + " null an ActivityResultCaller.");
    }

    /**
     * Get the FragmentManager if it's in Activity, or the ChildFragmentManager if it's in Fragment.
     *
     * @return The FragmentManager to operate Fragment.
     */
    @NonNull
    private FragmentManager fragmentManager() {
        if (lifecycleOwner instanceof Fragment) {
            return ((Fragment) lifecycleOwner).getChildFragmentManager();
        }
        if (lifecycleOwner instanceof FragmentActivity) {
            return ((FragmentActivity) lifecycleOwner).getSupportFragmentManager();
        }
        throw new IllegalStateException("PermissionDelegate " + this + " null an FragmentActivity.");
    }

    /**
     * Used to get the result for request multiple permissions.
     */
    @Nullable
    private ActivityResultLauncher<String[]> requestNormalPermissionLauncher;

    @NonNull
    private ActivityResultLauncher<String[]> getRequestNormalPermissionLauncher() {
        if (requestNormalPermissionLauncher != null) {
            return requestNormalPermissionLauncher;
        }
        return requestNormalPermissionLauncher = PermissionResultContracts.createMultiplePermission(requireActivityResultCaller(),
                new OnPermissionResultListener.onRefusedListener() {
                    @Override
                    public void onRefused(@NonNull List<String> permissions) {
                        onRequestNormalPermissionRefused(permissions);
                    }
                }, new OnPermissionResultListener.onSuccessListener() {
                    @Override
                    public void onSuccess() {
                        onRequestNormalPermissionSuccess();
                    }
                });
    }


    /**
     * Used to get the result for ACCESS_BACKGROUND_LOCATION permission.
     */
    @Nullable
    private ActivityResultLauncher<String> requestBackgroundLocationLauncher;

    @NonNull
    private ActivityResultLauncher<String> getRequestBackgroundLocationLauncher() {
        if (requestBackgroundLocationLauncher != null) {
            return requestBackgroundLocationLauncher;
        }
        return requestBackgroundLocationLauncher = PermissionResultContracts.createPermission(requireActivityResultCaller(),
                new ActivityResultCallback<Boolean>() {
                    @Override
                    public void onActivityResult(Boolean isSuccess) {
                        onRequestBackgroundLocationPermissionResult(isSuccess);
                    }
                });
    }

    /**
     * Used to get the result for ACCESS_BACKGROUND_LOCATION permission.
     */
    @Nullable
    private ActivityResultLauncher<String[]> requestBackgroundLocationFrontLauncher;

    @NonNull
    private ActivityResultLauncher<String[]> getRequestBackgroundLocationFrontLauncher() {
        if (requestBackgroundLocationFrontLauncher != null) {
            return requestBackgroundLocationFrontLauncher;
        }
        return requestBackgroundLocationFrontLauncher = PermissionResultContracts.createMultiplePermission(requireActivityResultCaller(),
                new OnPermissionResultListener.onRefusedListener() {
                    @Override
                    public void onRefused(@NonNull List<String> permissions) {
                        runResult(() -> {
                            // 请求被拒绝
                            onRefusedDialog(permissions);
                        });
                    }
                }, new OnPermissionResultListener.onSuccessListener() {
                    @Override
                    public void onSuccess() {
                        requestAccessBackgroundLocationPermissionNow();
                    }
                });
    }

    /**
     * Used to get the result for SYSTEM_ALERT_WINDOW permission.
     */
    @Nullable
    private ActivityResultLauncher<Intent> requestSystemAlertWindowLauncher;

    @NonNull
    private ActivityResultLauncher<Intent> getRequestSystemAlertWindowLauncher() {
        if (requestSystemAlertWindowLauncher != null) {
            return requestSystemAlertWindowLauncher;
        }
        return requestSystemAlertWindowLauncher = PermissionResultContracts.createResult(requireActivityResultCaller(),
                new ActivityResultCallback<ActivityResult>() {
                    @Override
                    public void onActivityResult(ActivityResult result) {
                        onRequestSystemAlertWindowPermissionResult();
                    }
                });
    }

    /**
     * Used to get the result for WRITE_SETTINGS permission.
     */
    @Nullable
    private ActivityResultLauncher<Intent> requestWriteSettingsLauncher;

    @NonNull
    private ActivityResultLauncher<Intent> getRequestWriteSettingsLauncher() {
        if (requestWriteSettingsLauncher != null) {
            return requestWriteSettingsLauncher;
        }
        return requestWriteSettingsLauncher = PermissionResultContracts.createResult(requireActivityResultCaller(),
                new ActivityResultCallback<ActivityResult>() {
                    @Override
                    public void onActivityResult(ActivityResult isSuccess) {
                        onRequestWriteSettingsPermissionResult();
                    }
                });
    }

    /**
     * Used to get the result for ACCESS_BACKGROUND_LOCATION permission.
     */
    @Nullable
    private ActivityResultLauncher<String[]> requestManageExternalStoragePermissionLauncher;

    @NonNull
    private ActivityResultLauncher<String[]> getRequestManageExternalStoragePermissionLauncher() {
        if (requestManageExternalStoragePermissionLauncher != null) {
            return requestManageExternalStoragePermissionLauncher;
        }
        return requestManageExternalStoragePermissionLauncher = PermissionResultContracts.createMultiplePermission(requireActivityResultCaller(),
                new OnPermissionResultListener.onRefusedListener() {
                    @Override
                    public void onRefused(@NonNull List<String> permissions) {
                        runResult(() -> {
                            // 请求被拒绝
                            onRefusedDialog(permissions);
                        });
                    }
                }, new OnPermissionResultListener.onSuccessListener() {
                    @Override
                    public void onSuccess() {
                        requestManageExternalStorageSettingsPermissionNow();
                    }
                });
    }

    /**
     * Used to get the result for MANAGE_EXTERNAL_STORAGE permission.
     */
    @Nullable
    private ActivityResultLauncher<Intent> requestManageExternalStorageLauncher;

    @NonNull
    private ActivityResultLauncher<Intent> getRequestManageExternalStorageLauncher() {
        if (requestManageExternalStorageLauncher != null) {
            return requestManageExternalStorageLauncher;
        }
        return requestManageExternalStorageLauncher = PermissionResultContracts.createResult(requireActivityResultCaller(),
                new ActivityResultCallback<ActivityResult>() {
                    @Override
                    public void onActivityResult(ActivityResult isSuccess) {
                        onRequestManageExternalStoragePermissionResult();
                    }
                });
    }

    /**
     * Used to get the result for REQUEST_INSTALL_PACKAGES permission.
     */
    @Nullable
    private ActivityResultLauncher<Intent> requestInstallPackagesLauncher;

    @NonNull
    private ActivityResultLauncher<Intent> getRequestInstallPackagesLauncher() {
        if (requestInstallPackagesLauncher != null) {
            return requestInstallPackagesLauncher;
        }
        return requestInstallPackagesLauncher = PermissionResultContracts.createResult(requireActivityResultCaller(),
                new ActivityResultCallback<ActivityResult>() {
                    @Override
                    public void onActivityResult(ActivityResult isSuccess) {
                        onRequestInstallPackagesPermissionResult();
                    }
                });
    }

    /**
     * Used to get the result for notification permission.
     */
    @Nullable
    private ActivityResultLauncher<Intent> requestNotificationLauncher;

    @NonNull
    private ActivityResultLauncher<Intent> getRequestNotificationLauncher() {
        if (requestNotificationLauncher != null) {
            return requestNotificationLauncher;
        }
        return requestNotificationLauncher = PermissionResultContracts.createResult(requireActivityResultCaller(),
                new ActivityResultCallback<ActivityResult>() {
                    @Override
                    public void onActivityResult(ActivityResult isSuccess) {
                        onRequestNotificationPermissionResult();
                    }
                });
    }

    /**
     * Used to get the result for BODY_SENSORS_BACKGROUND permission.
     */
    @Nullable
    private ActivityResultLauncher<String> requestBodySensorsBackgroundLauncher;

    @NonNull
    private ActivityResultLauncher<String> getRequestBodySensorsBackgroundLauncher() {
        if (requestBodySensorsBackgroundLauncher != null) {
            return requestBodySensorsBackgroundLauncher;
        }
        return requestBodySensorsBackgroundLauncher = PermissionResultContracts.createPermission(requireActivityResultCaller(),
                new ActivityResultCallback<Boolean>() {
                    @Override
                    public void onActivityResult(Boolean o) {
                        onRequestBodySensorsBackgroundPermissionResult(o);
                    }
                });
    }

    /**
     * Used to get the result when user switch back from Settings.
     */
    @Nullable
    private ActivityResultLauncher<Intent> forwardToSettingsLauncher;

    @NonNull
    private ActivityResultLauncher<Intent> getForwardToSettingsLauncher() {
        if (forwardToSettingsLauncher != null) {
            return forwardToSettingsLauncher;
        }
        return forwardToSettingsLauncher = PermissionResultContracts.createResult(requireActivityResultCaller(),
                new ActivityResultCallback<ActivityResult>() {
                    @Override
                    public void onActivityResult(ActivityResult isSuccess) {
                        onRequestForwardToSettings();
                    }
                });
    }

    /**
     * 设置界面返回
     */
    private void onRequestForwardToSettings() {
        if (specialPermissions.contains(PermissionConstants.ACCESS_BACKGROUND_LOCATION)) {
            onRequestBackgroundLocationPermissionResult(false);
            return;
        }
        if (specialPermissions.contains(PermissionConstants.MANAGE_EXTERNAL_STORAGE)) {
            onRequestManageExternalStoragePermissionResult();
            return;
        }
        if (specialPermissions.contains(PermissionConstants.REQUEST_INSTALL_PACKAGES)) {
            onRequestInstallPackagesPermissionResult();
            return;
        }
        if (specialPermissions.contains(PermissionConstants.POST_NOTIFICATIONS)) {
            onRequestNotificationPermissionResult();
            return;
        }
        if (specialPermissions.contains(PermissionConstants.BODY_SENSORS_BACKGROUND)) {
            onRequestBodySensorsBackgroundPermissionResult(false);
            return;
        }
        if (specialPermissions.contains(Manifest.permission.SYSTEM_ALERT_WINDOW)) {
            onRequestSystemAlertWindowPermissionResult();
            return;
        }
        if (specialPermissions.contains(Manifest.permission.WRITE_SETTINGS)) {
            onRequestWriteSettingsPermissionResult();
            return;
        }
        request();
    }

    /**
     * 权限申请成功
     */
    private void onRequestBackgroundLocationPermissionResult(boolean isSuccess) {
        runResult(() -> {
            if (isSuccess || PermissionX.canBackgroundLocation(requireActivity()) || Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
                onSuccess();
                return;
            }
            onRefusedDialog(Manifest.permission.ACCESS_BACKGROUND_LOCATION);
//            List<String> requestPermission = PermissionChecker.getRefusedPermission(requireActivity(), PermissionConstants.GROUP_LOCATION_BACKGROUND);
//            if (requestPermission.isEmpty()) {
//                return;
//            }
//            onRequestDialog(Manifest.permission.ACCESS_BACKGROUND_LOCATION);
        });
    }


    /**
     * 权限申请成功
     */
    private void onRequestNormalPermissionSuccess() {
        runResult(this::onSuccess);
    }

    /**
     * 权限申请失败  被拒绝
     */
    private void onRequestNormalPermissionRefused(@NonNull List<String> permissions) {
        runResult(() -> {
            onRefusedDialog(permissions);
        });
    }

    /**
     * SYSTEM_ALERT_WINDOW
     */
    private void onRequestSystemAlertWindowPermissionResult() {
        runResult(() -> {
            if (PermissionX.canSystemDialog(requireActivity())) {
                onSuccess();
            } else {
                onRefusedDialog(Manifest.permission.SYSTEM_ALERT_WINDOW);
            }
        });
    }

    /**
     * Handle result of WRITE_SETTINGS permission request.
     */
    private void onRequestWriteSettingsPermissionResult() {
        runResult(() -> {
            if (PermissionX.canWriteSettings(requireActivity())) {
                onSuccess();
            } else {
                onRefusedDialog(Manifest.permission.WRITE_SETTINGS);
            }
        });
    }

    /**
     * Handle result of MANAGE_EXTERNAL_STORAGE permission request.
     */
    private void onRequestManageExternalStoragePermissionResult() {
        runResult(() -> {
            if (PermissionX.canStorage()) {
                onSuccess();
            } else {
//                if (requestDialogListener != null) {
//                    onRequestDialog(PermissionConstants.MANAGE_EXTERNAL_STORAGE);
//                    return;
//                }
                onRefusedDialog(PermissionConstants.MANAGE_EXTERNAL_STORAGE);
            }
        });
    }

    /**
     * Handle result of notification permission request.
     */
    private void onRequestNotificationPermissionResult() {
        runResult(() -> {
            if (PermissionX.canNotifications(requireActivity())) {
                onSuccess();
            } else {
                onRefusedDialog(PermissionConstants.POST_NOTIFICATIONS);
            }
        });
    }

    /**
     * Handle result of REQUEST_INSTALL_PACKAGES permission request.
     */
    private void onRequestInstallPackagesPermissionResult() {
        runResult(() -> {
            if (PermissionX.canInstall(requireActivity())) {
                onSuccess();
            } else {
                onRefusedDialog(PermissionConstants.REQUEST_INSTALL_PACKAGES);
            }
        });
    }

    /**
     * Handle result of BODY_SENSORS_BACKGROUND permission request.
     */
    private void onRequestBodySensorsBackgroundPermissionResult(boolean isSuccessFul) {
        runResult(() -> {
            if (isSuccessFul) {
                onSuccess();
                return;
            }
            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
                onSuccess();
                return;
            }
            if (PermissionChecker.refused(requireActivity(), Manifest.permission.BODY_SENSORS_BACKGROUND)) {
                onRefusedDialog(Manifest.permission.BODY_SENSORS_BACKGROUND);
                return;
            }
            onRequestDialog(Manifest.permission.BODY_SENSORS_BACKGROUND);
        });
    }

    /**
     * Request permissions at once by calling [Fragment.requestPermissions],
     * and handle request result in ActivityCompat.OnRequestPermissionsResultCallback.
     *
     * @param permissions Permissions that you want to request.
     */
    private void requestNow(@NonNull List<String> permissions) {
        List<String> requestPermission = PermissionChecker.getRequestPermission(requireActivity(), permissions.toArray(new String[]{}));
        if (requestPermission.isEmpty()) {
            onSuccess();
            return;
        }
        getRequestNormalPermissionLauncher().launch(requestPermission.toArray(new String[]{}));
    }

    /**
     * Request ACCESS_BACKGROUND_LOCATION at once by calling [Fragment.requestPermissions],
     * and handle request result in ActivityCompat.OnRequestPermissionsResultCallback.
     */
    private void requestAccessBackgroundLocationPermissionNow() {
        if (PermissionX.canBackgroundLocation(requireActivity()) || Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
            onSuccess();
            return;
        }
        getRequestBackgroundLocationLauncher().launch(Manifest.permission.ACCESS_BACKGROUND_LOCATION);
    }

    private void requestAccessBackgroundLocationFrontPermissionNow() {
        List<String> requestPermission = PermissionChecker.getRequestPermission(requireActivity(), PermissionConstants.GROUP_LOCATION);
        if (!requestPermission.isEmpty()) {
            getRequestBackgroundLocationFrontLauncher().launch(PermissionConstants.GROUP_LOCATION);
            return;
        }
        requestAccessBackgroundLocationPermissionNow();
    }

    /**
     * Request SYSTEM_ALERT_WINDOW permission. On Android M and above, it's request by
     * Settings.ACTION_MANAGE_OVERLAY_PERMISSION with Intent.
     */
    private void requestSystemAlertWindowPermissionNow() {
        if (PermissionX.canSystemDialog(requireActivity())) {
            onSuccess();
        } else {
            getRequestSystemAlertWindowLauncher().launch(PermissionSettings.getAppSystemAlert(requireActivity()));
        }
    }

    /**
     * Request MANAGE_EXTERNAL_STORAGE permission. On Android R and above, it's request by
     * Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION with Intent.
     */
    private void requestManageExternalStorageSettingsPermissionNow() {
        if (PermissionX.canStorage()) {
            onSuccess();
        } else {
            getRequestManageExternalStorageLauncher().launch(PermissionSettings.getAppStorage(requireActivity()));
        }
    }

    private void requestManageExternalStoragePermissionNow() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
            List<String> requestPermission = PermissionChecker.getRequestPermission(requireActivity(), PermissionConstants.GROUP_STORAGE_ALL);
            if (requestPermission.isEmpty()) {
                requestManageExternalStorageSettingsPermissionNow();
                return;
            }
            getRequestManageExternalStoragePermissionLauncher().launch(PermissionConstants.GROUP_STORAGE_ALL);
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
            List<String> requestPermission = PermissionChecker.getRequestPermission(requireActivity(), PermissionConstants.GROUP_STORAGE);
            if (requestPermission.isEmpty()) {
                requestManageExternalStorageSettingsPermissionNow();
                return;
            }
            getRequestManageExternalStoragePermissionLauncher().launch(PermissionConstants.GROUP_STORAGE);
        } else {
            requestNow(Arrays.asList(PermissionConstants.GROUP_STORAGE));
        }
    }

    /**
     * Request WRITE_SETTINGS permission. On Android M and above, it's request by
     * Settings.ACTION_MANAGE_WRITE_SETTINGS with Intent.
     */
    private void requestWriteSettingsPermissionNow() {
        if (PermissionX.canWriteSettings(requireActivity())) {
            onSuccess();
        } else {
            getRequestWriteSettingsLauncher().launch(PermissionSettings.getAppWriteSettings(requireActivity()));
        }
    }

    /**
     * Request REQUEST_INSTALL_PACKAGES permission. On Android O and above, it's request by
     * Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES with Intent.
     */
    private void requestInstallPackagesPermissionNow() {
        if (PermissionX.canInstall(requireActivity())) {
            onSuccess();
        } else {
            getRequestInstallPackagesLauncher().launch(PermissionSettings.getAppInstall(requireActivity()));
        }
    }

    /**
     * Request notification permission. On Android O and above, it's request by
     * Settings.ACTION_APP_NOTIFICATION_SETTINGS with Intent.
     */
    private void requestNotificationPermissionNow() {
        if (PermissionX.canNotifications(requireActivity())) {
            onSuccess();
        } else {
            getRequestNotificationLauncher().launch(PermissionSettings.getAppNotification(requireActivity()));
        }
    }


    /**
     * Request BODY_SENSORS_BACKGROUND at once by calling [Fragment.requestPermissions],
     * and handle request result in ActivityCompat.OnRequestPermissionsResultCallback.
     */
    private void requestBodySensorsBackgroundPermissionNow() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
            if (PermissionX.hasPermission(requireActivity(), Manifest.permission.BODY_SENSORS_BACKGROUND)) {
                onSuccess();
                return;
            }
            getRequestBodySensorsBackgroundLauncher().launch(Manifest.permission.BODY_SENSORS_BACKGROUND);
        } else {
            onRequestBodySensorsBackgroundPermissionResult(true);
        }
    }

    /**
     * Go to your app's Settings page to let user turn on the necessary permissions.
     */
    public void forwardToSettings() {
        if (specialPermissions.contains(PermissionConstants.MANAGE_EXTERNAL_STORAGE)) {
            requestManageExternalStoragePermissionNow();
            return;
        }
        if (specialPermissions.contains(PermissionConstants.REQUEST_INSTALL_PACKAGES)) {
            requestInstallPackagesPermissionNow();
            return;
        }
        if (specialPermissions.contains(PermissionConstants.POST_NOTIFICATIONS)) {
            requestNotificationPermissionNow();
            return;
        }
        if (specialPermissions.contains(Manifest.permission.SYSTEM_ALERT_WINDOW)) {
            requestSystemAlertWindowPermissionNow();
            return;
        }
        if (specialPermissions.contains(Manifest.permission.WRITE_SETTINGS)) {
            requestWriteSettingsPermissionNow();
            return;
        }
        getForwardToSettingsLauncher().launch(PermissionSettings.getSetting(requireActivity()));
    }

    @Override
    public boolean isSuccess() {
        return isSuccess;
    }

    private void runResult(@NonNull Runnable runnable) {
        if (isMainThread()) {
            runnable.run();
            return;
        }
        requireActivity().runOnUiThread(runnable);
    }

    private static boolean isMainThread() {
        return Looper.getMainLooper().getThread() == Thread.currentThread();
    }

    @NonNull
    public PermissionRequest permissions(@NonNull String... permissions) {
        return permission(permissions);
    }

    @NonNull
    public PermissionRequest permissions(@NonNull List<String> permissions) {
        return permission(permissions.toArray(new String[]{}));
    }

    @NonNull
    public PermissionRequest permission(@NonNull String[] permissions) {
        this.permissions.clear();
        this.normalPermissions.clear();
        this.specialPermissions.clear();
        Collections.addAll(this.permissions, permissions);
        int osVersion = Build.VERSION.SDK_INT;
        int targetSdkVersion = requireActivity().getApplicationInfo().targetSdkVersion;
        List<String> allSpecialPermissions = Arrays.asList(PermissionConstants.allSpecialPermissions);
        for (String permission : permissions) {
            if (allSpecialPermissions.contains(permission)) {
                specialPermissions.add(permission);
            } else {
                normalPermissions.add(permission);
            }
        }
        if (specialPermissions.contains(PermissionConstants.ACCESS_BACKGROUND_LOCATION)) {
            if (osVersion == Build.VERSION_CODES.Q ||
                    (osVersion == Build.VERSION_CODES.R && targetSdkVersion < Build.VERSION_CODES.R)) {
                // If we request ACCESS_BACKGROUND_LOCATION on Q or on R but targetSdkVersion below R,
                // We don't need to request specially, just request as normal permission.
                specialPermissions.remove(PermissionConstants.ACCESS_BACKGROUND_LOCATION);
                normalPermissions.add(PermissionConstants.ACCESS_BACKGROUND_LOCATION);
            }
        }
        if (specialPermissions.contains(PermissionConstants.POST_NOTIFICATIONS)) {
            if (osVersion >= Build.VERSION_CODES.TIRAMISU && targetSdkVersion >= Build.VERSION_CODES.TIRAMISU) {
                // If we request POST_NOTIFICATIONS on TIRAMISU or above and targetSdkVersion >= TIRAMISU,
                // We don't need to request specially, just request as normal permission.
                specialPermissions.remove(PermissionConstants.POST_NOTIFICATIONS);
                normalPermissions.add(PermissionConstants.POST_NOTIFICATIONS);
            }
        }
        return this;
    }

    @NonNull
    public PermissionRequest onRefused(@Nullable OnPermissionResultListener.onRefusedListener refusedListener) {
        this.refusedListener = refusedListener;
        return this;
    }

    @NonNull
    public PermissionRequest onRefusedDialog(@Nullable OnPermissionResultListener.onRefusedDialogListener refusedDialogListener) {
        this.refusedDialogListener = refusedDialogListener;
        return this;
    }

    public PermissionRequest onRequestDialog(@Nullable OnPermissionResultListener.onRequestDialogListener requestDialogListener) {
        this.requestDialogListener = requestDialogListener;
        return this;
    }

    @NonNull
    public PermissionRequest onCancel(@Nullable OnPermissionResultListener.onCancelListener cancelListener) {
        this.cancelListener = cancelListener;
        return this;
    }

    @NonNull
    public PermissionRequest onSuccessFul(@Nullable OnPermissionResultListener.onSuccessFulListener successListener) {
        this.successFulListener = successListener;
        return this;
    }

    @NonNull
    @Override
    public PermissionRequest defaultDialog() {
        return onRefusedDialog(new OnPermissionResultListener.onRefusedDialogListener() {
            @Override
            public void onRefusedDialog(@NonNull PermissionRequest delegate, @NonNull List<String> permissions) {
                final ComponentActivity context = requireActivity();
                List<String> permissionNames = PermissionX.transformText(context, permissions);
                delegate.showPermissionDialog(
                        permissions,
                        "您已拒绝打开定位，请打开" + TextUtils.join("、", permissionNames),
                        "我明白了",
                        "取消",
                        false
                );
            }
        }).onRequestDialog(new OnPermissionResultListener.onRequestDialogListener() {
            @Override
            public void onRequestDialog(@NonNull PermissionRequest delegate, @NonNull List<String> permissions) {
                final ComponentActivity context = requireActivity();
                List<String> permissionNames = PermissionX.transformText(context, permissions);
                delegate.showPermissionDialog(
                        permissions,
                        "请打开" + TextUtils.join("、", permissionNames),
                        "我明白了",
                        "取消",
                        true
                );
            }
        });
    }

    private void onRefused(@NonNull List<String> permissions) {
        if (refusedListener != null) {
            refusedListener.onRefused(permissions);
        }
    }

    private void onRefusedDialog(@NonNull String permission) {
        if (refusedDialogListener != null) {
            List<String> permissions = new ArrayList<>();
            permissions.add(permission);
            onRefusedDialog(permissions);
        } else {
            onRefused(permissions);
        }
    }

    private void onRefusedDialog(@NonNull List<String> permissions) {
        if (refusedDialogListener != null) {
            refusedDialogListener.onRefusedDialog(this, permissions);
        } else {
            onRefused(permissions);
        }
    }

    private void onRequestDialog(@NonNull String permission) {
        if (requestDialogListener != null) {
            List<String> permissions = new ArrayList<>();
            permissions.add(permission);
            onRequestDialog(permissions);
        } else {
            onRefused(permissions);
        }
    }

    private void onRequestDialog(@NonNull List<String> permissions) {
        if (requestDialogListener != null) {
            requestDialogListener.onRequestDialog(this, permissions);
        } else {
            onRefused(permissions);
        }
    }

    private void onSuccess() {
        isSuccess = true;
        new Handler(Looper.getMainLooper())
                .postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        if (successListener != null) {
                            successListener.onSuccess();
                        }
                        if (successFulListener != null) {
                            successFulListener.onSuccess(PermissionDelegate.this);
                        }
                    }
                }, 100);
    }

    private void onCancel() {
        if (cancelListener != null) {
            cancelListener.onCancel();
        }
    }

    public void request(@NonNull OnPermissionResultListener.onSuccessListener successListener) {
        this.successListener = successListener;
        if (specialPermissions.contains(PermissionConstants.ACCESS_BACKGROUND_LOCATION)) {
            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q || PermissionX.canBackgroundLocation(requireActivity())) {
                onSuccess();
                return;
            }
//            if (PermissionChecker.refused(requireActivity(), Manifest.permission.ACCESS_BACKGROUND_LOCATION)) {
//                /// 权限被拒绝
//                if (requestDialogListener != null) {
//                    List<String> permissions = new ArrayList<>();
//                    permissions.add(Manifest.permission.ACCESS_BACKGROUND_LOCATION);
//                    onRequestDialog(permissions);
//                    return;
//                }
//            }
        }
        if (specialPermissions.contains(PermissionConstants.MANAGE_EXTERNAL_STORAGE)) {
            if (PermissionX.canStorage()) {
                onSuccess();
                return;
            }
        }
        if (specialPermissions.contains(PermissionConstants.REQUEST_INSTALL_PACKAGES)) {
            if (PermissionX.canInstall(requireActivity())) {
                onSuccess();
                return;
            }
        }
        if (specialPermissions.contains(PermissionConstants.POST_NOTIFICATIONS)) {
            if (PermissionX.canNotifications(requireActivity())) {
                onSuccess();
                return;
            }
        }
        if (specialPermissions.contains(PermissionConstants.BODY_SENSORS_BACKGROUND)) {
            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
                onSuccess();
                return;
            }
            if (PermissionX.hasPermission(requireActivity(), Manifest.permission.BODY_SENSORS_BACKGROUND)) {
                onSuccess();
                return;
            }
//            if (PermissionChecker.refused(requireActivity(), Manifest.permission.BODY_SENSORS_BACKGROUND)) {
//                /// 权限被拒绝
//                onRefusedDialog(Manifest.permission.BODY_SENSORS_BACKGROUND);
//                return;
//            }
        }
        if (specialPermissions.contains(Manifest.permission.SYSTEM_ALERT_WINDOW)) {
            if (PermissionX.canSystemDialog(requireActivity())) {
                onSuccess();
                return;
            }
        }
        if (specialPermissions.contains(Manifest.permission.WRITE_SETTINGS)) {
            if (PermissionX.canWriteSettings(requireActivity())) {
                onSuccess();
                return;
            }
        }
        List<String> requestPermission = PermissionChecker.getRequestPermission(requireActivity(), permissions);
        if (!requestPermission.isEmpty() && requestDialogListener != null) {
            onRequestDialog(requestPermission);
            return;
        }
//        if (specialPermissions.isEmpty()) {
//            // 没有特殊权限
//            List<String> requestPermission = PermissionChecker.getRequestPermission(requireActivity(), normalPermissions.toArray(new String[]{}));
//            if (requestPermission.isEmpty()) {
//                onSuccess();
//                return;
//            }
////            // 有需求请求的权限
////            List<String> refusedPermission = PermissionChecker.getRefusedPermission(requireActivity(), normalPermissions);
////            if (!refusedPermission.isEmpty()) {
////                /// 权限被拒绝
////                if (!requestPermission.isEmpty()) {
////                    onRequestDialog(requestPermission);
////                    return;
////                }
////                onRefusedDialog(refusedPermission);
////                return;
////            }
//            if (requestDialogListener != null) {
//                onRequestDialog(requestPermission);
//                return;
//            }
//        } else {
//            if (requestDialogListener != null) {
//                onRequestDialog(specialPermissions);
//                return;
//            }
//        }
        request();
    }

    private void request() {
        if (specialPermissions.contains(PermissionConstants.ACCESS_BACKGROUND_LOCATION)) {
            requestAccessBackgroundLocationFrontPermissionNow();
            return;
        }
        if (specialPermissions.contains(PermissionConstants.MANAGE_EXTERNAL_STORAGE)) {
            requestManageExternalStoragePermissionNow();
            return;
        }
        if (specialPermissions.contains(PermissionConstants.REQUEST_INSTALL_PACKAGES)) {
            requestInstallPackagesPermissionNow();
            return;
        }
        if (specialPermissions.contains(PermissionConstants.POST_NOTIFICATIONS)) {
            requestNotificationPermissionNow();
            return;
        }
        if (specialPermissions.contains(PermissionConstants.BODY_SENSORS_BACKGROUND)) {
            requestBodySensorsBackgroundPermissionNow();
            return;
        }
        if (specialPermissions.contains(Manifest.permission.SYSTEM_ALERT_WINDOW)) {
            requestSystemAlertWindowPermissionNow();
            return;
        }
        if (specialPermissions.contains(Manifest.permission.WRITE_SETTINGS)) {
            requestWriteSettingsPermissionNow();
            return;
        }
        requestNow(normalPermissions);
    }

    /**
     * This method is internal, and should not be called by developer.
     * <p>
     * <p>
     * Show a dialog to user and  explain why these permissions are necessary.
     *
     * @param permissions  Permissions to request again.
     * @param message      Message that explain to user why these permissions are necessary.
     * @param positiveText Positive text on the positive button to request again.
     * @param isRequest    Indicates should show explain reason or forward to Settings.
     */
    public void showPermissionDialog(
            @NonNull List<String> permissions,
            @NonNull String message,
            @NonNull String positiveText,
            boolean isRequest
    ) {
        showPermissionDialog(permissions, message, positiveText, "取消", isRequest);
    }

    /**
     * This method is internal, and should not be called by developer.
     * <p>
     * <p>
     * Show a dialog to user and  explain why these permissions are necessary.
     *
     * @param permissions  Permissions to request again.
     * @param message      Message that explain to user why these permissions are necessary.
     * @param positiveText Positive text on the positive button to request again.
     * @param negativeText Negative text on the negative button. Maybe null if this dialog should not be canceled.
     * @param isRequest    Indicates should show explain reason or forward to Settings.
     */
    public void showPermissionDialog(
            @NonNull List<String> permissions,
            @NonNull String message,
            @NonNull String positiveText,
            @Nullable String negativeText,
            boolean isRequest
    ) {
        DefaultDialog defaultDialog = new DefaultDialog(
                requireActivity(),
                permissions,
                message,
                positiveText,
                negativeText
        );
        showPermissionDialog(defaultDialog, isRequest);
    }

    /**
     * This method is internal, and should not be called by developer.
     * <p>
     * <p>
     * Show a dialog to user and  explain why these permissions are necessary.
     *
     * @param isRequest Indicates should show explain reason or forward to Settings.
     * @param dialog    Dialog to explain to user why these permissions are necessary.
     */
    public void showPermissionDialog(
            @NonNull RationaleDialog dialog,
            boolean isRequest
    ) {
        List<String> permissions = dialog.getPermissionsToRequest();
        if (permissions.isEmpty()) {
            // 这里不可能为空
            onSuccess();
            return;
        }
        dialog.show();
        if (dialog instanceof DefaultDialog && ((DefaultDialog) dialog).isPermissionLayoutEmpty()) {
            // No valid permission to show on the dialog.
            // We call dismiss instead.
            dialog.dismiss();
            onSuccess();
        }
        View positiveButton = dialog.getPositiveButton();
        View negativeButton = dialog.getNegativeButton();
        dialog.setCancelable(false);
        dialog.setCanceledOnTouchOutside(false);
        positiveButton.setClickable(true);
        positiveButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                dialog.dismiss();
                request(isRequest);
            }
        });
        if (negativeButton != null) {
            negativeButton.setClickable(true);
            negativeButton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    dialog.dismiss();
                    onCancel();
                }
            });
        }
    }

    public void request(boolean isRequest) {
        if (isRequest) {
            request();
        } else {
            forwardToSettings();
        }
    }

    /**
     * This method is internal, and should not be called by developer.
     * <p>
     * <p>
     * Show a DialogFragment to user and  explain why these permissions are necessary.
     *
     * @param isRequest      Indicates should show explain reason or forward to Settings.
     * @param dialogFragment DialogFragment to explain to user why these permissions are necessary.
     */
    public void showPermissionDialog(
            @NonNull RationaleDialogFragment dialogFragment,
            boolean isRequest
    ) {
        List<String> permissions = dialogFragment.getPermissionsToRequest();
        if (permissions.isEmpty()) {
            // 这里不可能为空
            onSuccess();
            return;
        }
        dialogFragment.showNow(fragmentManager(), "PermissionXRationaleDialogFragment");
        View positiveButton = dialogFragment.getPositiveButton();
        View negativeButton = dialogFragment.getNegativeButton();
        dialogFragment.setCancelable(false);
        positiveButton.setClickable(true);
        positiveButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                dialogFragment.dismiss();
                request(isRequest);
            }
        });
        if (negativeButton != null) {
            negativeButton.setClickable(true);
            negativeButton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    dialogFragment.dismiss();
                    onCancel();
                }
            });
        }
    }

    public void requestLocation(@NonNull OnPermissionResultListener.onSuccessListener successListener) {
        permission(PermissionConstants.GROUP_LOCATION)
                .request(successListener);
    }


    public void requestLocationBackground(@NonNull OnPermissionResultListener.onSuccessListener successListener) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            permissions(PermissionConstants.GROUP_LOCATION_ALL)
                    .request(successListener);
            return;
        }
        requestLocation(successListener);
    }


    public void requestCamera(@NonNull OnPermissionResultListener.onSuccessListener successListener) {
        permission(PermissionConstants.GROUP_CAMERA)
                .request(successListener);
    }


    public void requestAudio(@NonNull OnPermissionResultListener.onSuccessListener successListener) {
        permission(PermissionConstants.GROUP_AUDIO)
                .request(successListener);
    }

    public void requestAudio_33(@NonNull OnPermissionResultListener.onSuccessListener successListener) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
            permission(PermissionConstants.GROUP_AUDIO_33)
                    .request(successListener);
            return;
        }
        permission(PermissionConstants.GROUP_AUDIO)
                .request(successListener);
    }

    public void requestStorage(@NonNull OnPermissionResultListener.onSuccessListener successListener) {
        permission(PermissionConstants.GROUP_STORAGE)
                .request(successListener);
    }

    public void requestStorageR(@NonNull OnPermissionResultListener.onSuccessListener successListener) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
            permissions(PermissionConstants.GROUP_STORAGE_MANAGE)
                    .request(successListener);
            return;
        }
        requestStorage(successListener);
    }

    public void requestReadStorage(@NonNull OnPermissionResultListener.onSuccessListener successListener) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
            permission(PermissionConstants.GROUP_STORAGE_ALL)
                    .request(successListener);
            return;
        }
        requestStorageR(successListener);
    }

    public void requestAllStorage(@NonNull OnPermissionResultListener.onSuccessListener successListener) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
            permissions(PermissionConstants.GROUP_STORAGE_MANAGE)
                    .request(successListener);
            return;
        }
        requestStorageR(successListener);
    }

    @Override
    public void requestAllStorageCamera(@NonNull OnPermissionResultListener.onSuccessListener successListener) {
        requestAllStorage(() -> {
            requestCamera(successListener);
        });
    }

    public void requestPhone(
            @NonNull OnPermissionResultListener.onSuccessListener successListener) {
        permission(PermissionConstants.GROUP_PHONE)
                .request(successListener);
    }

    public void requestPhoneO(@NonNull OnPermissionResultListener.onSuccessListener successListener) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            permission(PermissionConstants.GROUP_PHONE_BELOW_O)
                    .request(successListener);
        } else {
            requestPhone(successListener);
        }
    }

    public void requestContacts(@NonNull OnPermissionResultListener.onSuccessListener successListener) {
        permission(PermissionConstants.GROUP_CONTACTS)
                .request(successListener);
    }

    public void requestCalendar(@NonNull OnPermissionResultListener.onSuccessListener successListener) {
        permission(PermissionConstants.GROUP_CALENDAR)
                .request(successListener);
    }

    public void requestSms(@NonNull OnPermissionResultListener.onSuccessListener successListener) {
        permission(PermissionConstants.GROUP_SMS)
                .request(successListener);
    }


    public void requestReadImage(@NonNull OnPermissionResultListener.onSuccessListener successListener) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
            permission(PermissionConstants.GROUP_IMAGES)
                    .request(successListener);
            return;
        }
        requestStorageR(successListener);
    }

    public void requestReadVideo(@NonNull OnPermissionResultListener.onSuccessListener successListener) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
            permission(PermissionConstants.GROUP_VIDEO)
                    .request(successListener);
            return;
        }
        requestStorageR(successListener);
    }

    public void requestSystemAlertWindow(@NonNull OnPermissionResultListener.onSuccessListener successListener) {
        permissions(Manifest.permission.SYSTEM_ALERT_WINDOW)
                .request(successListener);
    }

    public void requestWriteSettings(@NonNull OnPermissionResultListener.onSuccessListener successListener) {
        permissions(Manifest.permission.WRITE_SETTINGS)
                .request(successListener);
    }

    public void requestInstallPackages(@NonNull OnPermissionResultListener.onSuccessListener successListener) {
        permissions(PermissionConstants.REQUEST_INSTALL_PACKAGES)
                .request(successListener);
    }

    public void requestNotification(@NonNull OnPermissionResultListener.onSuccessListener successListener) {
        permissions(PermissionConstants.POST_NOTIFICATIONS)
                .request(successListener);
    }

    public void requestBodySensorsBackground(@NonNull OnPermissionResultListener.onSuccessListener successListener) {
        permissions(PermissionConstants.BODY_SENSORS_BACKGROUND)
                .request(successListener);
    }

    @Override
    public void dispose() {
        permissions.clear();
        normalPermissions.clear();
        specialPermissions.clear();
        refusedListener = null;
        successListener = null;
        refusedDialogListener = null;
        requestDialogListener = null;
        cancelListener = null;
        requestNormalPermissionLauncher = null;
        requestBackgroundLocationLauncher = null;
        requestNotificationLauncher = null;
        requestBodySensorsBackgroundLauncher = null;
        requestInstallPackagesLauncher = null;
        requestManageExternalStorageLauncher = null;
        requestSystemAlertWindowLauncher = null;
        requestWriteSettingsLauncher = null;
        forwardToSettingsLauncher = null;
        PermissionDelegate.this.lifecycleOwner = null;
    }

    @Override
    public PermissionRequest clearListener() {
        refusedListener = null;
        successListener = null;
        refusedDialogListener = null;
        requestDialogListener = null;
        cancelListener = null;
        return this;
    }
}
